{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "797f4471",
   "metadata": {},
   "source": [
    "# **Trabalho 2 - Memorial de Cálculo**\n",
    "\n",
    "**Disciplina:** PPGEE0017 - Projeto de Circuitos Integrados - PPGEEC/UFBA\n",
    "\n",
    "**Aluno:** André Paiva Conrado Rodrigues (N=2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42c3416e",
   "metadata": {},
   "source": [
    "## 1 - Escopo do trabalho\n",
    "\n",
    "\n",
    "### Especificações do circuito\n",
    "\n",
    "Extração de características de amplificador OTA Miller com os seguintes parâmetros:\n",
    "\n",
    "| **Parâmetro** | **Valor** | **Unidade**      |\n",
    "|---------------|-----------|------------------|\n",
    "| $W_{1,2}$     | 10        | $\\mu \\mathrm{m}$ |\n",
    "| $L_{1,2}$     | 2         | $\\mu \\mathrm{m}$ |\n",
    "| $W_{3,4}$     | 20        | $\\mu \\mathrm{m}$ |\n",
    "| $L_{3,4}$     | 2         | $\\mu \\mathrm{m}$ |\n",
    "| $W_5$         | 1         | $\\mu \\mathrm{m}$ |\n",
    "| $L_5$         | 1         | $\\mu \\mathrm{m}$ |\n",
    "| $W_6$         | 80        | $\\mu \\mathrm{m}$ |\n",
    "| $L_6$         | 0,5       | $\\mu \\mathrm{m}$ |\n",
    "| $W_7$         | 40        | $\\mu \\mathrm{m}$ |\n",
    "| $L_7$         | 20        | $\\mu \\mathrm{m}$ |\n",
    "| $C_L$         | 0,2       | pF               |\n",
    "| $C_M$         | 2,0       | pF               |\n",
    "| $V_{GG5}$     | -0,1      | V                |\n",
    "| $V_{DD}$      | 0,6       | V                |\n",
    "| $V_{SS}$      | -0,6      | V                |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "21d18879",
   "metadata": {},
   "source": [
    "### Parâmetros da Tecnologia\n",
    "\n",
    "| **Símbolo** | **Definição**                  | **Unidade** | **Canal N**            | **Canal P**            |\n",
    "|-------------|--------------------------------|-------------|------------------------|------------------------|\n",
    "| $I_{SQ}$    | Corrente de norm. (quadrado)   | nA          | 353,38                 | 49,514                 |\n",
    "| $n$         | Fator de rampa                 | -           | 1,3790                 | 1,2952                 |\n",
    "| $\\phi_{t}$  | Potencial Termodinâmico        | mV          | 26                     | 26                     |\n",
    "| $V_{T0}$    | Tensão de limiar no equilíbrio | V           | 0,3618                 | -0,3554                |\n",
    "| $U_{CRIT}$  | Campo Elétrico Crítico         | V/m         | $1,712 \\cdot 10^{6}$   | $6,960 \\cdot 10^{6}$   |\n",
    "| $D_{SUB}$   | Parâmetro de modelo DIBL       | -           | $4,057 \\cdot 10^{-6}$  | $3,781 \\cdot 10^{-3}$  |\n",
    "| $\\eta_{0}$  | Parâmetro de modelo DIBL       | -           | $2,750 \\cdot 10^{-6}$  | $1,151 \\cdot 10^{-3}$  |\n",
    "| $I_{t0}$    | Parâmetro de modelo DIBL       | m           | $3,1116 \\cdot 10^{-8}$ | $3,1116 \\cdot 10^{-8}$ |\n",
    "| $\\lambda$   | Parâmetro de modelo CLM        | -           | 1,9784                 | 0,8847                 |\n",
    "| $DL$        | Encurtamento do canal          | nm          | 10,4                   | 14,8                   |\n",
    "| $DW$        | Estreitamento do canal         | nm          | 0,24                   | 0                      |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b396eade",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Importação de bibliotecas\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "15b4a211",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Especificações do amplificador OTA Miller\n",
    "W_12 = 10e-6;   L_12 = 2e-6\n",
    "W_34 = 20e-6;   L_34 = 2e-6\n",
    "W_5 = 1e-6;     L_5 = 1e-6\n",
    "W_6 = 80e-6;    L_6 = 0.5e-6\n",
    "W_7 = 40e-6;    L_7 = 20e-6\n",
    "C_L = 0.2e-12\n",
    "C_M = 2e-12\n",
    "VGG5 = -0.1\n",
    "VDD = 0.6\n",
    "VSS = -0.6"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7bfd8ac4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Canal dos transistores\n",
    "pol_M12 = 'n'\n",
    "pol_M34 = 'p'\n",
    "pol_M5 = 'n'\n",
    "pol_M6 = 'p'\n",
    "pol_M7 = 'n'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "ca3dd6ae",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Parâmetros da tecnologia\n",
    "Isq_p = 49.514e-9;      Isq_n = 353.38e-9\n",
    "N_p = 1.2952;           N_n = 1.3790\n",
    "VT0_p = -0.3554;        VT0_n = 0.3618\n",
    "Phi_t = 26e-3\n",
    "Ucrit_p = 6.96e6;       Ucrit_n = 1.712e6\n",
    "Dsub_p = 3.781e-3;      Dsub_n = 4.057e-6\n",
    "Eta0_p = 1.151e-3;      Eta0_n = 2.75e-6\n",
    "It0 = 3.1116e-8\n",
    "lambda_p = 0.8847;      lambda_n = 1.9784\n",
    "DL_p = 14.8e-9;         DL_n = 10.4e-9\n",
    "DW_p = 0;               DW_n = 0.24e-9"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "891e3373",
   "metadata": {},
   "source": [
    "## 2 - Medições em simulação"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0ea802e6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Correntes de dreno medidas em simulação\n",
    "ID_M12 = 9.22461e-06 # Medido com sinal positivo\n",
    "ID_M34 = 9.22461e-06 # Medido com sinal negativo\n",
    "ID_M5 = 1.84492e-05 # Medido com sinal positivo\n",
    "ID_M6 = 6.60956e-05 # Medido com sinal negativo\n",
    "ID_M7 = 6.60956e-05 # Medido com sinal positivo\n",
    "\n",
    "# Tensão de offset\n",
    "Voffset = -259.17e-6"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c5819458",
   "metadata": {},
   "source": [
    "## 3 - Cálculo dos níveis de inversão"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "584abdbe",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Função para cálculo da corrente de normalização\n",
    "def is_calc(W, L, mos_pol):\n",
    "    if(mos_pol == 'p' or mos_pol == 'P'):\n",
    "        return Isq_p*W/L\n",
    "    elif(mos_pol == 'n' or mos_pol == 'N'):\n",
    "        return Isq_n*W/L\n",
    "    else:\n",
    "        return -np.inf\n",
    "\n",
    "# Função para cálculo de nível de inversão (sat.)\n",
    "def if_calc(Id, W, L, mos_pol):\n",
    "    if(mos_pol == 'p' or mos_pol == 'P' or mos_pol == 'n' or mos_pol == 'N'):\n",
    "        return Id/is_calc(W, L, mos_pol)\n",
    "    else:\n",
    "        return -np.inf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "74ef0d17",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I_F\n",
      "M1,2: 5.221 \n",
      "M3,4: 18.630 \n",
      "M5:   52.208\n",
      "M6:   8.343   \n",
      "M7:   93.519\n"
     ]
    }
   ],
   "source": [
    "If_M12 = if_calc(ID_M12, W_12, L_12, pol_M12)\n",
    "If_M34 = if_calc(ID_M34, W_34, L_34, pol_M34)\n",
    "If_M5 = if_calc(ID_M5, W_5, L_5, pol_M5)\n",
    "If_M6 = if_calc(ID_M6, W_6, L_6, pol_M6)\n",
    "If_M7 = if_calc(ID_M7, W_7, L_7, pol_M7)\n",
    "\n",
    "print(f\"I_F\\nM1,2: {If_M12:.3f} \\nM3,4: {If_M34:.3f} \\nM5:   {If_M5:.3f}\")\n",
    "print(f\"M6:   {If_M6:.3f}   \\nM7:   {If_M7:.3f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97a0f74e",
   "metadata": {},
   "source": [
    "|           | $I_{D} \\left( \\mu A \\right)$ | $I_{f}$ |\n",
    "|-----------|-----------------|---------|\n",
    "| $M_{1,2}$ | 9,22461         | 5,221   |\n",
    "| $M_{3,4}$ | 9,22461         | 18,630  |\n",
    "| $M_5$     | 18,4492         | 52,208  |\n",
    "| $M_6$     | 66,0956         | 8,343   |\n",
    "| $M_7$     | 66,0956         | 93,519  |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c239564d",
   "metadata": {},
   "source": [
    "## 4 - Cálculo dos parâmetros de desempenho"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "c1c4e935",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Cálculo da tensão de early mínima\n",
    "def early(L, mos_pol):\n",
    "    if(mos_pol == 'p' or mos_pol == 'P'):\n",
    "        L_eff = L - (2*DL_p)\n",
    "        theta_dibl = np.exp(-Dsub_p*L/(2*It0)) + (2*np.exp(-Dsub_p*L/It0))\n",
    "        sig = theta_dibl * Eta0_p\n",
    "        Va_min = ((L_eff*Ucrit_p) + Phi_t)/((sig/N_p) + lambda_p)\n",
    "    elif(mos_pol == 'n' or mos_pol == 'N'):\n",
    "        L_eff = L - (2*DL_n)\n",
    "        theta_dibl = np.exp(-Dsub_n*L/(2*It0)) + (2*np.exp(-Dsub_n*L/It0))\n",
    "        sig = theta_dibl * Eta0_n\n",
    "        Va_min = ((L_eff*Ucrit_n) + Phi_t)/((sig/N_n) + lambda_n)\n",
    "    else:\n",
    "        Va_min = -np.inf\n",
    "    return Va_min"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "66511a15",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Cálculo da transcondutância de dreno\n",
    "def g_md(Id, L, mos_pol):\n",
    "    if(mos_pol == 'p' or mos_pol == 'P' or mos_pol == 'n' or mos_pol == 'N'):\n",
    "        return Id/early(L, mos_pol)\n",
    "    else:\n",
    "        return -np.inf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "b72e2d4e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Cálculo da transcondutância de porta\n",
    "def g_mg(Id, W, L, mos_pol):\n",
    "    i_s = is_calc(W, L, mos_pol)\n",
    "    i_f = if_calc(Id, W, L, mos_pol)\n",
    "    if(mos_pol == 'p' or mos_pol == 'P'):\n",
    "        return ((2*i_s)/(N_p*Phi_t))*(np.sqrt(1+i_f) - 1)\n",
    "    elif(mos_pol == 'n' or mos_pol == 'N'):\n",
    "        return ((2*i_s)/(N_n*Phi_t))*(np.sqrt(1+i_f) - 1)\n",
    "    else:\n",
    "        return -np.inf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "7d5cad48",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Função para determinar f(i_f)\n",
    "def f_if(i_f):\n",
    "    return np.sqrt(i_f + 1) - 2 + np.log(np.sqrt(i_f + 1) - 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "15aaab56",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "G_MG \n",
      "M2: 1.473e-04 \n",
      "M6: 9.677e-04 \n",
      "\n",
      "G_MD \n",
      "M2: 5.345e-06 \n",
      "M4: 5.954e-07 \n",
      "M6: 1.777e-05 \n",
      "M7: 3.820e-06\n"
     ]
    }
   ],
   "source": [
    "# Transcondutâncias úteis\n",
    "gmg_M2 = g_mg(ID_M12, W_12, L_12, pol_M12)\n",
    "gmg_M6 = g_mg(ID_M6, W_6, L_6, pol_M6)\n",
    "gmd_M2 = g_md(ID_M12, L_12, pol_M12)\n",
    "gmd_M4 = g_md(ID_M34, L_34, pol_M34)\n",
    "gmd_M6 = g_md(ID_M6, L_6, pol_M6)\n",
    "gmd_M7 = g_md(ID_M7, L_7, pol_M7)\n",
    "\n",
    "print(f\"G_MG \\nM2: {gmg_M2:.3e} \\nM6: {gmg_M6:.3e} \\n\")\n",
    "print(f\"G_MD \\nM2: {gmd_M2:.3e} \\nM4: {gmd_M4:.3e} \\nM6: {gmd_M6:.3e} \\nM7: {gmd_M7:.3e}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "86b46ad1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " Ad0 = 60.915 dB \n",
      " GBW = 52065946 Hz\n",
      "  PM = 83.241° \n",
      "  SR = 9.225 V/us\n",
      "CMR+ = 0.592 \n",
      "CMR- = 0.163\n",
      "-0.269 <= Vout <= 0.443\n"
     ]
    }
   ],
   "source": [
    "# Ganho diferencial em baixas frequências\n",
    "Ad0 = (gmg_M2*gmg_M6)/((gmd_M2 + gmd_M4)*(gmd_M6 + gmd_M7))\n",
    "Ad0_dB = 20*np.log10(Ad0)\n",
    "\n",
    "# Produto Ganho-Largura de Banda\n",
    "GBW = gmg_M2/(np.sqrt(2)*C_M) # Hz\n",
    "\n",
    "# Margem de fase\n",
    "omg_p2 = gmg_M6/C_L; omg_z = gmg_M6/C_M\n",
    "PM = ((np.pi/2) - np.arctan(GBW/omg_p2) - np.arctan(GBW/omg_z))*180/np.pi\n",
    "\n",
    "# Slew Rate\n",
    "SR = min((ID_M5/C_M), (ID_M7/C_L))*1e-6 # V/us\n",
    "\n",
    "# Faixa de modo comum\n",
    "CMR_p = N_n*(VDD - (N_p*Phi_t*f_if(If_M34)) + VT0_p + (Phi_t*f_if(If_M12)) - VSS - (Phi_t*(np.sqrt(If_M12+1)+3))) + VSS + VT0_n\n",
    "CMR_n = N_n*Phi_t*(f_if(If_M12) + np.sqrt(If_M5+1) + 3) + VSS + VT0_n\n",
    "\n",
    "# Limites da tensão de saída\n",
    "Vout_min = Phi_t*(np.sqrt(1 + If_M7)+3) + VSS\n",
    "Vout_max = VDD - Phi_t*(np.sqrt(1 + If_M6)+3)\n",
    "\n",
    "print(f\" Ad0 = {Ad0_dB:.3f} dB \\n GBW = {(GBW):.0f} Hz\")\n",
    "print(f\"  PM = {PM:.3f}° \\n  SR = {SR:.3f} V/us\")\n",
    "print(f\"CMR+ = {CMR_p:.3f} \\nCMR- = {CMR_n:.3f}\")\n",
    "print(f\"{Vout_min:.3f} <= Vout <= {Vout_max:.3f}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
